﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using Sripirom.Pattern.UnitTest.Core.Domain;
using Sripirom.Pattern.UnitTest.Core.UnitOfWork;
using Sripirom.Pattern.UnitTest.Model.TestCases;

namespace Sripirom.Pattern.UnitTest.Repository.Configuration
{
    public  class XmlUnitOfWork : IUnitOfWork
    {
      //  private IDictionary<Type, IUnitOfWorkRepository> _dictionary = new Dictionary<Type, IUnitOfWorkRepository>();

        PersitController _collection;
        public XmlUnitOfWork()
        {
            _collection = new PersitController();
        }

        //public XmlUnitOfWork RegisPersitRepository(Type entityType, IUnitOfWorkRepository repository)
        //{
        //   // _dictionary.Add(entityType, repository);
        //    return this;
        //}

        public void Commit()
        {
            if (_collection == null)
                throw new InvalidOperationException();

            try
            {
                // tells the file watcher that he cannot raise the changed event, because his function is to capture external change.
                _collection.Commit();
            }
            catch (Exception)
            {

                throw;
            }                            
        }

        public void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)
        {
            _collection.Push(entity, unitofWorkRepository, RepositoryCommand.RegisterAmended);
        }

        public void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)
        {
            _collection.Push(entity, unitofWorkRepository, RepositoryCommand.RegisterNew);
        }

        public void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)
        {
            _collection.Push(entity, unitofWorkRepository, RepositoryCommand.RegisterRemoved);
        }

        public void Evict(Core.Domain.IAggregateRoot entity)
        {
            throw new NotImplementedException();
        }
    }

    public enum RepositoryCommand
    {
        RegisterAmended,
        RegisterNew,
        RegisterRemoved
    }
    public class PersitController
    {
        Stack<Tuple<IAggregateRoot, IUnitOfWorkRepository, RepositoryCommand>> _collection;

        public PersitController()
        {
            _collection = new Stack<Tuple<IAggregateRoot, IUnitOfWorkRepository, RepositoryCommand>>();
        }

        public void Push(IAggregateRoot entity, IUnitOfWorkRepository repository, RepositoryCommand command) 
        {
            _collection.Push(new Tuple<IAggregateRoot, IUnitOfWorkRepository, RepositoryCommand>(entity, repository, command));
        }

        public void Commit()
        {
            foreach (var item in _collection)
            {
                switch (item.Item3)
                {
                    case RepositoryCommand.RegisterAmended:
                        item.Item2.PersistUpdateOf(item.Item1);
                        break;
                    case RepositoryCommand.RegisterNew:
                        item.Item2.PersistCreationOf(item.Item1);
                        break;
                    case RepositoryCommand.RegisterRemoved:
                        item.Item2.PersistDeletionOf(item.Item1);
                        break;
                    default:
                        break;
                }
            }
        }

    }
}
